Release 10.1A: OpenEdge Development:
ProDataSets
Running standard validation procedures on update
There are no standard event hooks for
SAVE-ROW-CHANGESas there are forFILLbecause, generally, validation logic will be executed before or possibly after theSAVE-ROW-CHANGESmethod, so there is nowhere for Progress to execute standard events. Instead, you can execute whatever validation logic or other business logic you need to before or after runningSAVE-ROW-CHANGES.Because
commitChanges.psimulates what aSAVE-CHANGESmethod on the whole ProDataSet would do, there are places within this procedure where standard event hooks can go. This section shows you how you can add event hooks of this kind to yourcommitChangesprocedure.
![]()
To add event hooks to
commitChanges.p:
- Add a
HANDLEvariablehSourceProcand assign it to theSOURCE-PROCEDURE, as shown:
Validation procedures will be executed in the calling procedure from the internal procedure
saveBuffer. At the timecommitChanges.pis run, the calling procedure’s handle is theSOURCE-PROCEDURE. By running validation in the caller, you can code validation logic directly into the entity procedure or into another procedure that you run as a super procedure of the entity. The problem is that from within an internal procedure likesaveBuffer, called from the main block, the value ofSOURCE-PROCEDUREiscommitChanges.pitself. For this reason the new code saves off the value ofSOURCE-PROCEDUREin the main block so that it can be referenced insaveBuffer.The rest of the changes are to the internal procedure
saveBuffer.- Add a variable definition to
saveBufferfor a character string to hold a procedure name:
The new code assumes a naming convention of the temp-table name plus
Delete,Create, orModifyfor validation logic procedures. For example, a procedure to execute when attOlinerecord is modified is calledttOlineModify. You’ll code just such a procedure below. Add this statement to generate the procedure name at the beginning of theDOblock that walks through the dynamic query:
Before the code runs the logic procedure it needs to find the right after-table row so that the validation procedure can see its values. Remember that the dynamic query
hBeforeQryis navigating the rows of the before-table. The after-table rows aren’t automatically found, so you need this statement to bring the corresponding after-table row into its own buffer:
Now you can run the logic procedure if it exists. The code passes the ProDataSet as
INPUTBY-REFERENCEjust as Progress does forFILLevent procedures. Remember that anINPUTparameter passedBY-REFERENCEto a local procedure is effectively the same as anINPUT-OUTPUTparameter, because any changes made are visible to the caller. Nonetheless, we pass the ProDataSet asINPUTfor consistency with the calling sequence ofFILLevents, as shown:
The validation procedure can set the
ERRORattribute for the row if it fails validation. If this isn’t the case then it runsSAVE-ROW-CHANGESon the row.After this, if the
ERRORattribute has been set either by the validation procedure or bySAVE-ROW-CHANGESitself, the code setsERRORon the ProDataSet itself. This is because when your code setsERRORon a row programmatically, Progress does not set it on the ProDataSet. This happens only when Progress detects an error internally and setsERRORon both the row and the ProDataSet. For example:
As before, the code also sets the
REJECTEDflag.Now you have a general-purpose save procedure that also runs general-purpose business logic at key points during the update process.
- Open the procedure
OrderEntity.p, whereOrder-specific business logic goes, and create an internal procedurettOlineModifythat compares some values in the before- and after-tables for the currentttOlinerow.If the
Quantityorder has been doubled or more, then the procedure rewards the customer by increasing the discount by 20%. On the other hand, if theQuantityhas been cut by half or more, this is considered an error and the procedure sets theERRORflag and also anERROR-STRINGmessage. For example:
Even though
saveBufferpasses the ProDataSet as a dynamicDATASET-HANDLE(because it has only a dynamic reference to the ProDataSet),ttOlineModifycan receive it as a staticDATASET, matching its local definition, so that you can code static 4GL statements for your business logic.Now if you re-run the window you can see the effects.
- Run
dsOrderWinAdv.w. Select anOrder, increase oneQtyby more than double, and cut another by more than half:
![]()
In this case, we doubled the
QtyforLine Number 2, and the discount was increased accordingly. We decreased theQtyforLine Number 3by more than half, and that change was rejected and the message displayed. This is an example of why you might not want to runMERGE-CHANGESon the whole ProDataSet when not all changes were successful. The original values for the rejected row are redisplayed and the user’s changes erased. It would probably be better to runMERGE-ROW-CHANGESjust on successful updates and leave the incorrect values for other rows so that they can be seen and more easily corrected.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |